package com.hz.house.service;

import com.hz.house.bean.entity.SellManYesterdayStar;
import com.hz.house.bean.vo.SellManCachedBasicInfoBean;
import com.hz.house.dao.SellManMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.ReturnType;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * redis数据缓存服务
 * @author lfw
 *
 */
@Service
public class RedisCacheDataService {

	@Autowired
	private RedisTemplate<String,Object> redis;
	
	public static final String  UC_MAX_ID = "house_customer_maxid";
	
	public static final String UC_TEMP_RES = "user_login_temp_res:";
	
	public static final String SELL_MAN_ALL_CACHE = "sell_man_all_basic";

	public static final String ENCODE_PHONE_NUMBER = "encode_phone_number";
	
	public static final String SELL_MAN_YESTERDAY_STAR = "sell_man_yesterday_stars";

	public static final String SELL_MAN_YESTERDAY_BUILD_STAR = "sell_man_yesterday_build_stars";
	
	public static final String SELL_MAN_ADDSCORE_LIMIT = "sellman_addscore_limit:";
	
	public static final String SELL_MAN_SCORE_SHARE_CUSTOMERID_TEMP="sell_man_score_share_temp_customerId";
	public static final String SELL_MAN_SCORE_SHARE_CUSTOMERID__SCOREID_TEMP="sell_man_score_share_temp_sidcidscoreid";
	
	public static final String WXGZH_SELLHOUSE_ACCTK= "wxgzh_sellhouse_acctk";
	
	public static final String CUSTOMER_ZIXUN_SELLMAN_KEY="customer_sellman:";
	
	public static final String COIN_MAX_CHUJIA_TODAY = "today_max_coin";
	
	public static final String LPR1_MONTH ="lpr1_rate";
	public static final String LPR2_MONTH ="lpr2_rate";
	
	@Autowired
	private SellManMapper sellManMapper;
	
	/**设置用户的最大id，不删除改缓存*/
	public void setUserMaxId(int maxId) {
		this.redis.opsForValue().set(UC_MAX_ID, maxId);
	}
	
	/**用户id自动加1脚本，分布式下安全*/
	private String incrementScript= ""
			+ "local key = KEYS[1];"
			+ "local val = redis.call('get',key);"
			+ "if(val == 'nil' or val == false)"
			+ "then"
			+ "		return 0;"
			+ "		end;"
			+ "local maxid = redis.call('incrby',key,1);"
			+ "return maxid;";
	
	
	/**
	 *  <p> 从redis获取用户的自增id
	 * @return
	 */
	public Integer getIncrementUserId() {
		
		long maxId = redis.execute((RedisCallback<Long>) connection -> {
			Long x = connection.eval(incrementScript.getBytes(),ReturnType.INTEGER,1,
					(UC_MAX_ID).getBytes());
			return x;
		});
		return (int)maxId;
	}
	
	
	/**获取避免并发登录的临时缓存用户id*/
	@SuppressWarnings("unchecked")
	public Map<String,Object> getTempUserLoginRes(String openid) {
		return (Map<String,Object>) redis.opsForValue().get(UC_TEMP_RES+openid);
	}
	
	/**缓存5秒登录用户登录结果id**/
	public void setTempUserLoginRes(String openid, Map<String,Object> loginRes) {
		redis.opsForValue().set(UC_TEMP_RES+openid, loginRes, 5, TimeUnit.SECONDS);
	}
	
	/**
	 * 缓存所有置业顾问的基本信息
	 * @param all
	 */
	public void setAllSellManCache(List<SellManCachedBasicInfoBean> all) {
		
		Map<String,Object> m = new HashMap<String, Object>();
		all.forEach(s->{
			m.put(s.getCustormerId()+"", s);
		});
		redis.opsForHash().putAll(SELL_MAN_ALL_CACHE, m);
		redis.expire(SELL_MAN_ALL_CACHE, 30, TimeUnit.HOURS);
	}
	
	/**删除所有置业顾问缓存信息*/
	public void deleteAllSellManCache() {
		this.redis.delete(SELL_MAN_ALL_CACHE);
	}
	
	
	/**
	 *    获取置业顾问的基本信息,如果没有缓存则同步
	 *    
	 * @param customerId
	 * @return
	 */
	public SellManCachedBasicInfoBean getSellManBasicInfo(Integer customerId) {
		SellManCachedBasicInfoBean x = (SellManCachedBasicInfoBean) redis.opsForHash()
				.get(SELL_MAN_ALL_CACHE, customerId+"");
		if(x==null) {
			if(!redis.hasKey(SELL_MAN_ALL_CACHE)) {
				//没有key则同步所有数据
				this.setAllSellManCache(this.sellManMapper.getSellMan(null));
			}else {
				//有则同步本职业顾问信息
				this.setAllSellManCache(this.sellManMapper.getSellMan(String.valueOf(customerId)));
			}
			x = (SellManCachedBasicInfoBean) redis.opsForHash()
					.get(SELL_MAN_ALL_CACHE, customerId+"");
		}
		return x;
	}

	public String getEncodePhoneNumber(String from, String to){
		if (to.isEmpty()){
			return "";
		}

		return "";
	}
 
	
	@SuppressWarnings("unchecked")
	public List<SellManYesterdayStar> getYesterdayStars(Integer buildingId){
		if (ObjectUtils.isEmpty(buildingId)){
			return (List<SellManYesterdayStar>) this.redis.opsForValue().get(SELL_MAN_YESTERDAY_STAR);
		}
		return (List<SellManYesterdayStar>) redis.opsForHash().get(SELL_MAN_YESTERDAY_BUILD_STAR, buildingId);
	}
	
	/**
	 * 	设置昨日之星
	 * @param stars
	 */
	public void setYesterdayStars(List<SellManYesterdayStar> stars, Integer buildingId) {
		if (ObjectUtils.isEmpty(buildingId)){
			this.redis.opsForValue().set(SELL_MAN_YESTERDAY_STAR, stars, 25,TimeUnit.HOURS);
			return;
		}
		redis.opsForHash().put(SELL_MAN_YESTERDAY_BUILD_STAR, buildingId, stars);
		this.redis.expire(SELL_MAN_YESTERDAY_BUILD_STAR,25,TimeUnit.HOURS);
	}
	
	/**删除昨日之星*/
	public void deleteYesterdayStars(Integer buildingId) {
		if (!ObjectUtils.isEmpty(buildingId)){
			redis.opsForHash().delete(SELL_MAN_YESTERDAY_BUILD_STAR, buildingId);
			return;
		}
		this.redis.delete(SELL_MAN_YESTERDAY_STAR);
	}
	
	/**初始化置业顾问的加分限制:share_new,share_old分享，reply回复：晚上十二点删除*/
	public void initSellManAddScoreLimit(int sellManCustomerId,String type) {
		this.redis.opsForHash().put(SELL_MAN_ADDSCORE_LIMIT+sellManCustomerId, type, 1);
		this.redis.expire(SELL_MAN_ADDSCORE_LIMIT+sellManCustomerId,30,TimeUnit.HOURS);
	}
	
	/**删除所有置业顾问的分享当天限制*/
	public void deleteSellManShareLimitCache(List<Integer> sellmanIds) {
		List<String> keys = new ArrayList<String>();
		sellmanIds.forEach(id->{
			keys.add(SELL_MAN_ADDSCORE_LIMIT+id);
		});
		this.redis.delete(keys);
	}
	
	//判断是否超限值，没有则+1返回原值，否则返回0则没有了
	private String addLimitScript = ""
			+ "local x = redis.call('hget',KEYS[1],KEYS[2]);"
			+ "if(x==false) then"
			+ "  return -1;"
			+ "  end;"
			+ "local nx = tonumber(x);"
			+ "local l = tonumber(ARGV[1]);"
			+ "if(nx >= l) then"
			+ " return 0;"
			+ "	end;"
			+ "local v = nx+1;"//执行自增，不管他加分是否成功
			+ "redis.call('hset',KEYS[1],KEYS[2],v);"
			+ "return nx;";
	
	/***获取置业顾问加分项当前类型的当前已经执行了次数*/
	public Long getSellManAddScoreLimitNow(int sellManCustomerId,String type,Integer limit) {
		Long x = redis.execute(new RedisCallback<Long>() {
			@Override
			public Long doInRedis(RedisConnection connection) throws DataAccessException {
				Long x = connection.eval(addLimitScript.getBytes(),ReturnType.INTEGER,2, 
						(SELL_MAN_ADDSCORE_LIMIT+sellManCustomerId).getBytes(),
						type.getBytes(),limit.toString().getBytes());
				return x;
			}
		});
		return x;
	}
 
	
	/**晚上十二点要删除这个key*/
	public Long setCustomerIdForRepeat(Integer customerId) {
		return redis.opsForSet().add(SELL_MAN_SCORE_SHARE_CUSTOMERID_TEMP,customerId);
	}
	
	/**删除用户点击分享加分的缓存记录*/
	public void deleteCustomerIdForRepeat() {
		this.redis.delete(SELL_MAN_SCORE_SHARE_CUSTOMERID_TEMP);
	}
	/**晚上十二点要删除这个key*/
	public Long setCustomerId_ScoreId_SellmanIdForRepeat(String id) {
		return redis.opsForSet().add(SELL_MAN_SCORE_SHARE_CUSTOMERID__SCOREID_TEMP,id);
	}
	
	/**删除用户点击分享加分的缓存记录*/
	public void deleteCustomerId_ScoreId_SellmanIdForRepeat() {
		this.redis.delete(SELL_MAN_SCORE_SHARE_CUSTOMERID__SCOREID_TEMP);
	}
	
	/**将用户id从临时表里删除*/
	public void removeCustomerIdForRepeat(Integer customerId) {
		redis.opsForSet().remove(SELL_MAN_SCORE_SHARE_CUSTOMERID_TEMP, customerId);
	}
 
	/**卖房好帮手的微信公众号token*/
	public void setWxgzhSellHouseAcctk(String acctk) {
		this.redis.opsForValue().set(WXGZH_SELLHOUSE_ACCTK, acctk, 2, TimeUnit.HOURS);
	}
	
	/**获取卖房好帮手的公众token*/
	public String getWxgzhSellHouseAcctk() {
		return (String) this.redis.opsForValue().get(WXGZH_SELLHOUSE_ACCTK);
	}
	
	/**设置用户的发送间隔时间*/
	public boolean setNxCustomerIdSellManId(int customerId,int sellManId) {
		return this.redis.opsForValue().setIfAbsent(CUSTOMER_ZIXUN_SELLMAN_KEY+customerId+sellManId, 
				"1", 30, TimeUnit.MINUTES);
	}
	
	private String coinMaxScript = ""
			+ "local max = redis.call('get',KEYS[1]);"
			+ "if(max=='nil' or max==false) then"
			+ "		redis.call('set',KEYS[1],ARGV[1]);"
			+ "		return 0;"
			+ "		end;"
			+ "local x = tonumber(max);"
			+ "local e = tonumber(ARGV[1]);"
			+ "if(x>e or x==e) then"
			+ "		return 1;"
			+ "		end;"
			+ "redis.call('set',KEYS[1],e);"
			+ "return 0;";
		 
	
			 
	
	 
	public boolean isExceedTodayMaxCoin(int myCoin) {
		//如果脚本执行结果为1小于等于最大值，0则大于最大值
		Long x = redis.execute(new RedisCallback<Long>() {
			@Override
			public Long doInRedis(RedisConnection connection) throws DataAccessException {
				Long x = connection.eval(coinMaxScript.getBytes(),ReturnType.INTEGER,1,
						COIN_MAX_CHUJIA_TODAY.getBytes(),String.valueOf(myCoin).getBytes());
				return x;
			}
		});
		return x==0;
	}
	
	/**删除今日最高金币缓存*/
	public void deleteTodayMaxCoin() {
		this.redis.delete(COIN_MAX_CHUJIA_TODAY);
	}
	
	/**获取今天置业顾问上首页出价金币最高价*/
	public Integer getNowMaxCoin() {
		return (Integer) this.redis.opsForValue().get(COIN_MAX_CHUJIA_TODAY);
	}
	
	/**删除首页金牌置业顾问*/
	public void deleteGodenSellManCache() {
		this.redis.delete("home_golden_sale_man_V2_2");
	}
	
	/**获取设置的lpr值*/
	public String getLpr() {
		Double lpr1 = (Double) this.redis.opsForValue().get(LPR1_MONTH);
		Double lpr2 =  (Double) this.redis.opsForValue().get(LPR2_MONTH);
		if(lpr1==null || lpr2==null)
			return null;
		return lpr1+","+lpr2;
	}
	
}
